/*
 * $Id: $
 */
package org.rcgwt.client.ui.grid.internal;

import org.rcgwt.client.ui.grid.internal.model.IElementModel;
import org.rcgwt.client.ui.grid.internal.model.IElementModelDelta;

/**
 * 
 * @author Olivier Oeuillot (latest modification by $Author: $)
 * @version $Revision: $ $Date: $
 */
public abstract class AbstractModelElementDelta<T extends IElementModel>
        implements IElementModelDelta<T> {

    private static final IElementModelDelta< ? > EMPTY_ARRAY[] = new IElementModelDelta[0];

    private final T elementModel;

    private IElementModelDelta< ? extends IElementModel> childrenDeltas[];

    private int childrenDeltasCount = 0;

    protected AbstractModelElementDelta(T elementModel) {
        this.elementModel = elementModel;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <C extends IElementModel> IElementModelDelta<C> getChildDelta(
            C modelElement) {
        if (childrenDeltas == null) {
            childrenDeltas = new IElementModelDelta< ? >[2];

        } else {
            for (int i = 0; i < childrenDeltasCount; i++) {
                IElementModelDelta< ? > childDelta = childrenDeltas[i];

                if (childDelta.getModelElement().equals(modelElement)) {
                    return (IElementModelDelta<C>) childDelta;
                }
            }

        }

        IElementModelDelta<C> childDelta = createChildDelta(modelElement);

        if (childrenDeltasCount < childrenDeltas.length) {
            childrenDeltas[childrenDeltasCount++] = childDelta;
            return childDelta;
        }

        IElementModelDelta< ? > newCildrenDeltas[] = new IElementModelDelta[childrenDeltasCount + 4];
        System.arraycopy(childrenDeltas, 0, newCildrenDeltas, 0,
                childrenDeltasCount);

        newCildrenDeltas[childrenDeltasCount++] = childDelta;
        childrenDeltas = newCildrenDeltas;

        return childDelta;
    }

    @SuppressWarnings("unchecked")
    protected <C extends IElementModel> IElementModelDelta<C> createChildDelta(
            C elementModel) {
        return (IElementModelDelta<C>) elementModel.createDelta();
    }

    @Override
    public T getModelElement() {
        return elementModel;
    }

    @Override
    public IElementModelDelta< ? extends IElementModel>[] listChildrenDeltas() {
        if (childrenDeltas == null) {
            return EMPTY_ARRAY;
        }

        return childrenDeltas;
    }

    @Override
    public String toString(String prefix) {
        String s = prefix + toString() + "\n";

        String p = prefix + "  ";
        for (int i = 0; i < childrenDeltasCount; i++) {
            s += childrenDeltas[i].toString(p);
        }

        return s;
    }

}
